package cn.com.godliu.gateway;

import cn.com.godliu.gateway.filters.GlobalFilter;
import cn.com.godliu.gateway.filters.LocalGatewayFilterFactory;
import io.github.resilience4j.circuitbreaker.CircuitBreakerConfig;
import io.github.resilience4j.timelimiter.TimeLimiterConfig;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.circuitbreaker.resilience4j.Resilience4JCircuitBreakerFactory;
import org.springframework.cloud.circuitbreaker.resilience4j.Resilience4JConfigBuilder;
import org.springframework.cloud.client.circuitbreaker.Customizer;
import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
import org.springframework.context.annotation.Bean;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.reactive.CorsWebFilter;
import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.util.pattern.PathPatternParser;
import reactor.core.publisher.Mono;

import java.time.Duration;

@Slf4j
@SpringBootApplication
public class GatewayApplication {

    public static void main(String[] args) {
        SpringApplication.run(GatewayApplication.class, args);
    }

    @Bean
    public CorsWebFilter corsFilter() {
        CorsConfiguration config = new CorsConfiguration();
        config.addAllowedMethod("*");//支持所有方法
        config.addAllowedOrigin("*");//跨域处理 允许所有的域
        config.addAllowedHeader("*");//支持所有请求头

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(new PathPatternParser());
        source.registerCorsConfiguration("/**", config);//匹配所有请求

        return new CorsWebFilter(source);
    }

    /*******************全局过滤器和自定义过滤器的使用*************************/
    @Bean
    public GlobalFilter globalFilter() {
        return new GlobalFilter();
    }

    @Bean
    public LocalGatewayFilterFactory localGatewayFilterFactory() {
        return new LocalGatewayFilterFactory();
    }

    /**
     * 网关断路配置，当请求响应时间大于设置的阈值，将请求发送到回调上，以提高体验感知
     *
     * @return
     */
    @Bean
    public Customizer<Resilience4JCircuitBreakerFactory> defaultCustomizer() {
        return factory -> factory.configureDefault(id -> new Resilience4JConfigBuilder(id)
                .timeLimiterConfig(TimeLimiterConfig.custom().timeoutDuration(Duration.ofSeconds(1)).build())//将超过时间的请求发送到circuit服务的回调上
                .circuitBreakerConfig(CircuitBreakerConfig.ofDefaults())
                .build());
    }

    /**************************三种限流方式**********************************/
    /**
     * 限流配置-用户ip作为限流
     * @return
     */
    //@Bean
    //public KeyResolver hostAddrKeyResolver() {
    //    //获取请求用户ip作为限流key
    //    return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getHostName());
    //}

    /**
     * 限流配置-用户id作为限流
     */
//    @Bean
//    public KeyResolver userKeyResolver() {
//        //获取请求用户id作为限流key。
//        return exchange -> Mono.just(exchange.getRequest().getQueryParams().getFirst("userId"));
//    }

    /**
     * 限流配置-请求地址的uri作为限流
     */
    //@Bean
    //public KeyResolver apiKeyResolver() {
    //    //获取请求地址的uri作为限流key。
    //    return exchange -> Mono.just(exchange.getRequest().getPath().value());
    //}

    /************************************************************************************/

}
